/*
 * $Id: api_getmeminfo.c,v 1.1 2006-02-22 04:51:51 bacon Exp $
 */

#include <xp/sys/api.h>

#if defined(_WIN32)
	#include <pdh.h>
#elif defined(__linux)
	#include <sys/sysinfo.h>
	#include <sys/sysctl.h>
#elif defined(__FreeBSD__)
	#include <kvm.h>
	#include <fcntl.h>
	#include <sys/sysctl.h>
#elif defined(sun)||defined(__sun)
	#include <sys/sysinfo.h>
#else
	#include <sys/sysctl.h>
#endif

/* TODO: implant an option to return the size in kbytes */
int xp_getmeminfo (xp_meminfo_t* mem)
{
#if defined(_WIN32) 
	#if (_WIN32_WINNT<0x0500)

	MEMORYSTATUS status;
	GlobalMemoryStatus(&status);
	mem->totalram = status.dwTotalPhys;
	mem->freeram = status.dwAvailPhys;
	mem->totalswap = status.dwTotalVirtual;
	mem->freeswap = status.dwAvailVirtual;

	#else

	MEMORYSTATUSEX status;
	if (GlobalMemoryStatusEx(&status) == FALSE) return -1;
	mem->totalram = status.ullTotalPhys;
	mem->freeram = status.ullAvailPhys;
	mem->totalswap = status.ullTotalVirtual;
	mem->freeswap = status.ullAvailVirtual;

	#endif

	mem->availram = mem->totalram - mem->freeram;
	mem->availswap = mem->totalswap - mem->freeswap;
	return 0;
#elif defined(__linux)

	struct sysinfo info;

	if (sysinfo (&info) == -1) return -1;
#ifdef XP_HAVE_SYS_SYSINFO_MEM_UNIT
	mem->totalram = info.totalram * info.mem_unit;
	mem->freeram = info.freeram * info.mem_unit;
	mem->totalswap = info.totalswap * info.mem_unit;
	mem->freeswap = info.freeswap * info.mem_unit;
#else
	mem->totalram = info.totalram;
	mem->freeram = info.freeram;
	mem->totalswap = info.totalswap;
	mem->freeswap = info.freeswap;
#endif

	mem->availram = mem->totalram - mem->freeram;
	mem->availswap = mem->totalswap - mem->freeswap;

/*
	xp_sio_t sio;
	xp_char_t buf[1024];
	xp_size_t idx;
	int match_mem = 0, match_swap = 0;

	if (xp_sio_open(&sio, 
		XP_TEXT("/proc/meminfo"), XP_TEXT("r")) == XP_NULL) return -1;

	for (idx = 0; idx < 6; idx++) mem[idx] = 0;

	while (xp_sio_gets(&sio, buf, sizeof(buf)) > 0) {
		xp_char_t* p = buf;

		while (xp_isspace(*p)) p++;
		if (p[0] == XP_CHAR('M') && p[1] == XP_CHAR('e') && 
		    p[2] == XP_CHAR('m') && p[3] == XP_CHAR(':')) {
			p += 4; match_mem = 1;
			for (idx = 0; idx < 3; idx++) {
				while (xp_isspace(*p)) p++;
				while (xp_isdigit(*p)) {
					mem[idx] = mem[idx] * 10 + (*p++ - XP_CHAR('0'));
				}
			}
		}
		else if (p[0] == XP_CHAR('S') && p[1] == XP_CHAR('w') &&
		         p[2] == XP_CHAR('a') && p[3] == 'p' && p[4] == XP_CHAR(':')) {
			p += 5; match_swap = 1;
			for (idx = 3; idx < 6; idx++) {
				while (xp_isspace(*p)) p++;
				while (xp_isdigit(*p)) {
					mem[idx] = mem[idx] * 10 + (*p++ - XP_CHAR('0'));
				}
			}
		}
		else if (!match_mem &&
		         xp_strcmpn(p, XP_TEXT("MemTotal:"), 9) == 0) {
			p += 9; while (xp_isspace(*p)) p++;
			while (xp_isdigit(*p)) mem[0] = mem[0] * 10 + (*p++ - XP_CHAR('0'));
		}
		else if (!match_mem && mem[0] > 0 &&
		         xp_strcmpn(p, XP_TEXT("MemFree:"), 8) == 0) {
			p += 8; while (xp_isspace(*p)) p++;
			while (xp_isdigit(*p)) mem[2] = mem[2] * 10 + (*p++ - XP_CHAR('0'));
			mem[1] = mem[0] - mem[2];
		}
		else if (!match_swap && 
		         xp_strcmpn(p, XP_TEXT("SwapTotal:"), 10) == 0) {
			p += 10; while (xp_isspace(*p)) p++;
			while (xp_isdigit(*p)) mem[3] = mem[3] * 10 + (*p++ - XP_CHAR('0'));
		}
		else if (!match_swap && mem[3] > 0 && 
		         xp_strcmpn(p, XP_TEXT("SwapFree:"), 9) == 0) {
			p += 9; while (xp_isspace(*p)) p++;
			while (xp_isdigit(*p)) mem[5] = mem[5] * 10 + (*p++ - XP_CHAR('0'));
			mem[4] = mem[3] - mem[5];
		}
	}
	xp_sio_close (&sio);

	if (!match_mem) { for (idx = 0; idx < 3; idx++) mem[idx] *= 1024; }
	if (!match_swap) { for (idx = 4; idx < 6; idx++) mem[idx] *= 1024; }
*/

	return 0;
#elif defined(__FreeBSD__)
	/*
	kvm_t* kvm;
	
	kvm = kvm_open (XP_NULL, XP_NULL, XP_NULL, O_RDONLY, "kvm_open");
	if (kvm == XP_NULL) return -1;

	kvm_close (kvm);
	return 0;
	*/
	return -1;
#else
	return -1;
#endif
}
